# Description
Luogu 传送门
# Solution
(感谢 @Acestar 提供的思路)
初始情况下,每头奶牛匹配一个礼物,所以我们把奶牛和礼物当作一个点。
如果奶牛 非常不要脸的去抢奶牛 的礼物( 向 连单向边),而且不幸的是奶牛 还打不过奶牛 ,那么 就被迫去抢别人的礼物 qwq,所以 就必须向它能抢到的别的奶牛连边。
因此我们这个图就建出来了,找一组解只需要跑一遍传递闭包即可,顺便拿个 优化一下,时间复杂度 ,跑的飞快。
# Code
@ShuKuang 已经成功卡到了目前最优解。
顺便感谢他提供的代码(
#include <bits/stdc++.h> | |
using namespace std; | |
namespace IO { | |
template <typename T> | |
inline void read(T &x) { | |
x = 0; T r = 1; | |
char ch = getchar(); | |
while (!isdigit(ch)) r = ch == '-' ? -1 : 1, ch = getchar(); | |
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); | |
x *= r; | |
} | |
template <typename T, typename ...Args> | |
void read(T &x, Args &...args) { | |
read(x), read(args...); | |
} | |
template <typename T> | |
inline void write(T x) { | |
if (x < 0) putchar('-'), x = -x; | |
if (x > 9) write(x / 10); | |
putchar(x % 10 + '0'); | |
} | |
} | |
using namespace IO; | |
bitset<511> f[511]; | |
short n; | |
short a[511][511]; | |
signed main() { | |
read(n); | |
for (short i = 1; i <= n; ++ i) { | |
for (short j = 1; j <= n; ++ j) { | |
read(a[i][j]); | |
} | |
} | |
for (short i = 1; i <= n; ++ i) { | |
for (short j = 1; j <= n; ++ j) { | |
if (a[i][j - 1] == i) break; | |
f[i][a[i][j]] = 1; | |
} | |
} | |
for (short j = 1; j <= n; ++ j) { | |
for (short i = 1; i <= n; ++ i) { | |
if (f[i][j]) | |
f[i] |= f[j]; | |
} | |
} | |
for (short i = 1; i <= n; ++ i) { | |
for (short j = 1; j <= n; ++ j) { | |
if (f[i][a[i][j]] && f[a[i][j]][i]) { | |
write(a[i][j]), putchar('\n'); | |
break; | |
} | |
} | |
} | |
} |